package com.example.ass7.dataloader;

import java.awt.Color;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import com.example.ass7.geometryprimitives.Point;
import com.example.ass7.helper.Convertor;
import com.example.ass7.level.DataLevel;
import com.example.ass7.level.LevelInformation;
import com.example.ass7.sprite.Block;

/**
 * @author Meirav Ben Izhak
 */
public class LevelSpecificationReader {

    private static final String START_LEVEL_KEY = "START_LEVEL";
    private static final String LEVEL_NAME_KEY = "level_name";
    private static final String BALL_VELOCITIES_KEY = "ball_velocities";
    private static final String BACKGROUND_KEY = "background";
    private static final String PADDLE_SPEED_KEY = "paddle_speed";
    private static final String PADDLE_WIDTH_KEY = "paddle_width";
    private static final String BLOCK_DEFINITIONS_KEY = "block_definitions";
    private static final String BLOCKS_START_X_KEY = "blocks_start_x";
    private static final String BLOCKS_START_Y_KEY = "blocks_start_y";
    private static final String ROW_HEIGHT_KEY = "row_height";
    private static final String NUM_BLOCKS_KEY = "num_blocks";
    private static final String START_BLOCKS_KEY = "START_BLOCKS";
    private static final String END_BLOCKS_KEY = "END_BLOCKS";
    private static final String END_LEVEL_KEY = "END_LEVEL";

    private BlocksFromSymbolsFactory factory = new BlocksFromSymbolsFactory();

    /**
     * @param reader
     *            reader
     * @return List
     * @throws IOException
     *             IOException
     */
    public List<LevelInformation> fromReader(java.io.Reader reader)
           throws IOException {
        List<LevelInformation> levels = new ArrayList<LevelInformation>();
        BufferedReader br = new BufferedReader(reader);
        DataLevel data = new DataLevel();
        while (br.ready()) {
            String line = br.readLine();
            if (line != null
                    && !line.isEmpty()) {

                line = line.trim();
                if (line.startsWith("#")) {
                    continue;
                }

                if (line.equals(START_LEVEL_KEY)) {
                    data = new DataLevel();
                } else if (line.equals(END_LEVEL_KEY)) {
                    levels.add(data);
                } else if (line.equals(START_BLOCKS_KEY)) {
                    String tempLine = br.readLine();
                    int yBegin = (int) data.getCenterBlock().getY();
                    while (tempLine != null
                            && !tempLine.isEmpty()
                            && !END_BLOCKS_KEY.equalsIgnoreCase(tempLine)) {
                        tempLine = tempLine.trim();
                        if (tempLine.startsWith("#")) {
                            continue;
                        }

                        int xBegin = (int) data.getCenterBlock().getX();
                        for (int indx = 0; indx < tempLine.length(); indx++) {
                            String s = String.valueOf(tempLine.charAt(indx));
                            if (this.factory.isBlockSymbol(s)) {
                                Block block = this.factory.getBlock(s,
                                        xBegin,
                                        yBegin);
                                xBegin += block.getCollisionRectangle()
                                        .getWidth();
                                data.addBlock(block);
                            } else if (this.factory.isSpaceSymbol(s)) {
                                int width = this.factory.getSpaceWidth(s);
                                xBegin += width;
                            }
                        }
                        yBegin = yBegin
                                + data.getRowHeight();
                        tempLine = br.readLine();
                    }
                } else {
                    String[] pair = line.split(":");
                    if (pair != null
                            && pair.length == 2) {
                        String key = pair[0].trim();
                        String value = pair[1].trim();
                        this.mappingLevelData(key,
                                value,
                                data);
                    }
                }
            }
        }

        return levels;
    }

    /**
     * @param key
     *            key
     * @param value
     *            value
     * @param data
     *            data
     * @throws IOException
     *             IOException
     */
    private void mappingLevelData(String key,
            String value,
            DataLevel data) throws IOException {
        if (data == null) {
            return;
        }
        if (LEVEL_NAME_KEY.equals(key)) {
            data.setLevelName(value);
        } else if (BACKGROUND_KEY.equals(key)) {
            Background background = new Background(null, Color.white);
            if (value.startsWith("color(")) {
                ColorsParser colorsParser = new ColorsParser();
                background = colorsParser.colorFromString(value);

            } else if (value.startsWith("image(")) {
//                String filename = value.substring(6).replace(")",
//                        "");
                InputStream inputStream =
                        LevelSpecificationReader.class
                        .getResourceAsStream("/block_images/alien.png");
                Image image = ImageIO.read(inputStream);
                background = new Background(image, null);

            }
            data.setBackground(background);
        } else if (PADDLE_SPEED_KEY.equals(key)) {
            data.setPaddleSpeed(Convertor.parseInt(value));
        } else if (PADDLE_WIDTH_KEY.equals(key)) {
            data.setPaddleWidth(Convertor.parseInt(value));
        } else if (BLOCK_DEFINITIONS_KEY.equals(key)) {
            BlocksDefinitionReader blokDefReader = new BlocksDefinitionReader();
            InputStream inputStream =
                    LevelSpecificationReader.class
                    .getResourceAsStream(value);
            Reader reader = new InputStreamReader(inputStream);
            this.factory = blokDefReader.fromReader(reader);
        } else if (BLOCKS_START_X_KEY.equals(key)) {
            Point center = data.getCenterBlock();
            if (center == null) {
                center = new Point(0.0, 0.0);
                data.setCenterBlock(center);
            }
            center.setX(Convertor.parseDouble(value));
        } else if (BLOCKS_START_Y_KEY.equals(key)) {
            Point center = data.getCenterBlock();
            if (center == null) {
                center = new Point(0.0, 0.0);
                data.setCenterBlock(center);
            }
            center.setY(Convertor.parseDouble(value));
        } else if (ROW_HEIGHT_KEY.equals(key)) {
            data.setRowHeight(Convertor.parseInt(value));
        }
    }
}